/*
============================================================================
 Name        : dd_http_worker.c
 Author      : Jian
 Version     :
 Copyright   : GPL
 Description : dd_http_worker.c - source file
============================================================================
*/

/* INCLUDE FILES */
#include "dd_http_worker.h"
#include "dd_task_worker.h"
#include "dd_log.h"

#include "sd_platform.h"

enum {
    EHttpTaskGet  = 0,
    EHttpTaskPostBuf,
    EHttpTaskPostFile,
    EHttpTaskHead,
    EHttpTaskMultiGet
} ;

/* don't modify the member order of bellow 2 struct, because the __task_type(task) use this special order */

typedef struct {
    dd_task     task ;
    int         type;       
    int         priority ;
    const void* reqData;
} dd_http_task;


typedef struct {
    dd_task                task ;
    int                    type;
    int                    priority ;
    const dd_http_req_get* oriData;
    dd_http_req_get        wrapper ;   /* midware of the oriData and dd_http */
} dd_http_multi_get_task;

#define __task_type(task)  (((dd_http_task*)task)->type)

static int _task_priority(dd_task* task) 
{
    dd_http_task* normalTask = (dd_http_task*)task ;
    __DD_ASSERT_DEFENSE(normalTask, return -1) ;
    return normalTask->priority ;
}

static void _task_work(dd_task* task) 
{
    dd_http_task* normalTask = (dd_http_task*)task ;

    __DD_ASSERT_DEFENSE(normalTask, return) ;
    
    switch (__task_type(task)) 
    {
    case EHttpTaskGet:
        dd_http_get((const dd_http_req_get*)normalTask->reqData) ;
        break ;

    case EHttpTaskPostBuf:
        dd_http_post_buffer((const dd_http_req_post_buf*)normalTask->reqData) ;
        break; 

    case EHttpTaskPostFile:
        dd_http_post_file((const dd_http_req_post_file*)normalTask->reqData) ;
        break;
        
    case EHttpTaskHead:
        dd_http_head((const dd_http_req_head*)normalTask->reqData) ;
        break; 
    
    default:
        dd_log_error("fatal error that type: %d is error in _task_work", __task_type(task)) ;
        break; 
    }
}

static void _task_destroy(dd_task* task) 
{
    dd_http_task* normalTask = (dd_http_task*)task ;
    __DD_ASSERT_DEFENSE(normalTask, return) ;

    dd_free(normalTask) ;
}

dd_task* _create_normal_task(int type, const void* data, int priority) 
{
    dd_http_task* task = dd_malloc(sizeof(dd_http_task)) ;
    __DD_CHECK_MEM(task, sizeof(dd_http_task), return NULL) ;

    task->type     = type ;
    task->reqData  = data ;
    task->priority = priority ;

    task->task.work     = _task_work ;
    task->task.priority = _task_priority ;
    task->task.destroy  = _task_destroy ;

    return (dd_task*)task ;
}


static int _multi_get_task_priority(dd_task* task) 
{
    dd_http_multi_get_task* multiTask = (dd_http_multi_get_task*)task ;
    __DD_ASSERT_DEFENSE(multiTask, return -1) ;

    return multiTask->priority ;
}

static void _multi_get_task_work(dd_task* task) 
{
    dd_http_multi_get_task* multiTask = (dd_http_multi_get_task*)task ;
    __DD_ASSERT_DEFENSE(multiTask, return) ;
}

static void _multi_get_task_destroy(dd_task* task) 
{
    dd_http_multi_get_task* multiTask = (dd_http_multi_get_task*)task ;
    __DD_ASSERT_DEFENSE(multiTask, return) ;
}


static int _multi_get_http_start(dd_http* http) 
{
    dd_http_multi_get_task* multiTask = (dd_http_multi_get_task*)http->callback.clientPtr ;
    __DD_ASSERT_DEFENSE(multiTask, return -1) ;

    return 0 ;
}

static int _multi_get_http_is_cancel(const dd_http* http) 
{
    dd_http_multi_get_task* multiTask = (dd_http_multi_get_task*)http->callback.clientPtr ;
    __DD_ASSERT_DEFENSE(multiTask, return 1) ;

    return 0 ;
}

static int _multi_get_http_process_header(const dd_http* http) 
{
    dd_http_multi_get_task* multiTask = (dd_http_multi_get_task*)http->callback.clientPtr ;
    __DD_ASSERT_DEFENSE(multiTask, return -1) ;

    return 0 ;
}

static int _multi_get_http_process_body(const dd_http* http, const char* htData, int offset, int len) 
{
    dd_http_multi_get_task* multiTask = (dd_http_multi_get_task*)http->callback.clientPtr ;
    __DD_ASSERT_DEFENSE(multiTask, return -1) ;

    return 0 ;
}   

static void _multi_get_http_finish(const dd_http* http, int errorCode) 
{
    dd_http_multi_get_task* multiTask = (dd_http_multi_get_task*)http->callback.clientPtr ;
    __DD_ASSERT_DEFENSE(multiTask, return) ;
}



dd_task* _create_multi_get_task(const dd_http_req_get* data, int priority) 
{
    dd_http_multi_get_task* task = dd_malloc(sizeof(dd_http_multi_get_task)) ;
    __DD_CHECK_MEM(task, sizeof(dd_http_multi_get_task), return NULL) ;
    
    task->priority = priority ;

    /* we wrap a new dd_http_callback interfaces */
    task->oriData = data ;
    
    task->wrapper.callback.clientPtr      = task ;
    task->wrapper.callback.start          = _multi_get_http_start ;
    task->wrapper.callback.is_cancel      = _multi_get_http_is_cancel ;
    task->wrapper.callback.process_header = _multi_get_http_process_header ;
    task->wrapper.callback.process_body   = _multi_get_http_process_body ;
    task->wrapper.callback.finish         = _multi_get_http_finish ;

    task->task.work     = _multi_get_task_work ;
    task->task.priority = _multi_get_task_priority ;
    task->task.destroy  = _multi_get_task_destroy ;

    return (dd_task*)task ;
}

dd_http_worker* dd_http_worker_create(DD_UINT startTaskId, int threadCount) 
{
    dd_http_worker* worker = dd_malloc(sizeof(dd_http_worker)) ;

    __DD_CHECK_MEM(worker, sizeof(dd_http_worker), return NULL) ;
    
    if (threadCount <= 0) {
        threadCount = sd_get_cpu_count() * 2 ;
        __DD_ASSERT_DEFENSE(threadCount > 0, threadCount = 2) ;
    } 
    
    worker->taskWorker = dd_worker_create(startTaskId, threadCount, 1) ;
    __DD_ASSERT_DEFENSE(worker->taskWorker, return NULL) ;

    return worker ;
}

void dd_http_worker_destroy(dd_http_worker* worker) 
{
    __DD_ASSERT_DEFENSE(worker, return) ;

    dd_worker_destroy(worker->taskWorker) ;
    dd_free(worker) ;
}

DD_UINT dd_http_worker_get(dd_http_worker* worker, const dd_http_req_get* req, int isEnableMultiGet, int priority) 
{
    __DD_ASSERT_DEFENSE(worker && req, return DD_INVALID_TASK_ID) ;

    return dd_worker_add(worker->taskWorker, isEnableMultiGet ? _create_multi_get_task(req, priority) : _create_normal_task(EHttpTaskGet, req, priority)) ;
}

DD_UINT dd_http_worker_post_buf(dd_http_worker* worker, const dd_http_req_post_buf* req, int priority) 
{
    __DD_ASSERT_DEFENSE(worker && req, return DD_INVALID_TASK_ID) ;

    return dd_worker_add(worker->taskWorker, _create_normal_task(EHttpTaskPostBuf, req, priority)) ;
}

DD_UINT dd_http_worker_post_file(dd_http_worker* worker, const dd_http_req_post_file* req, int priority) 
{
    __DD_ASSERT_DEFENSE(worker && req, return DD_INVALID_TASK_ID) ;

    return dd_worker_add(worker->taskWorker, _create_normal_task(EHttpTaskPostFile, req, priority)) ;
}

DD_UINT dd_http_worker_head(dd_http_worker* worker, const dd_http_req_head* req, int priority) 
{
    __DD_ASSERT_DEFENSE(worker && req, return DD_INVALID_TASK_ID) ;

    return dd_worker_add(worker->taskWorker, _create_normal_task(EHttpTaskHead, req, priority)) ;
}

static void _cancel_http(dd_task* task) 
{
    int type = 0 ;

    __DD_ASSERT_DEFENSE(task, return) ;
    
    type = __task_type(task) ;

}

int dd_http_worker_cancel(dd_http_worker* worker, DD_UINT taskId) 
{
    __DD_ASSERT_DEFENSE(worker && taskId != DD_INVALID_TASK_ID, return -1) ;

    dd_worker_update(worker->taskWorker, taskId, _cancel_http) ;
}

/* End of File */
